package com.zach.util;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 配置文件辅助工具<br/>
 * 用于读取、修改配置属性<br/>
 * 默认的配置文件名为“config.xml”位于类路径的根目录下。
 * @author john
 *
 */
public class ConfigUtil {
	private static Logger log =  LoggerFactory.getLogger(ConfigUtil.class);
	private static boolean logDebugFlag = log.isDebugEnabled();
	private static Path path = new Path();;
	/**
	 * 通过文件名，来取得文件
	 * @param fileName
	 * @return
	 */
	private static File getAbsoluteFile(String fileName){
		File f = new File(path.getPath(),fileName);
		return f;
	}
	/**
	 * 从默认的类路径下的“config.xml”文件中读取配置信息
	 * @param section 模块名
	 * @param propName 配置属性名
	 * @return
	 */
	public static String  getConfValue(String section,String propName){
		return getConfValue("config.xml", section, propName);
	}
	/**
	 * 从xml配置文件中读取一个配置的属性值 
	 * @param conFileName 属性文件名，必须是类路径下的。
	 * @param section 所属模块
	 * @param propName 属性名
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static String  getConfValue(String conFileName,String section,String propName){
		if(logDebugFlag){
			log.debug("read config property from file:classpath://"+conFileName);
			log.debug("section:"+section+" \t propertyName:"+propName);
		}
		String result=null;
		SAXReader sreader= new SAXReader();
		Document document;
		boolean finding=true;//是否还要查找 
		try {
			File f = getAbsoluteFile(conFileName);
			if(!f.exists()) return result;
			if(logDebugFlag){
				log.debug("文件路径："+f.getAbsolutePath());
			}
			document = sreader.read(f);
			
			Element root = document.getRootElement();
			Element sec;
			for(Iterator<Element> sects=root.elementIterator();sects.hasNext()&&finding;){
				sec=sects.next();
				if(logDebugFlag){
					log.debug("模块 "+sec.attributeValue("name"));
				}
				if(sec.attributeValue("name").equalsIgnoreCase(section)){
					if(logDebugFlag){
						log.debug("   找到模块 "+section);
					}
					Element prop;
					for(Iterator<Element> props=sec.elementIterator();props.hasNext()&&finding;){
						prop = props.next();
						if(logDebugFlag){
							log.debug("         属性 "+prop.attributeValue("name"));
						}
						if(prop.attributeValue("name").equalsIgnoreCase(propName)){
							result=prop.getTextTrim();
							if(logDebugFlag){
								log.debug("property value:"+result);
							}
							finding=false;
							break;
						}
					}
				}
			}
			if(finding){
				log.info("属性 "+propName+" 没有找到");
			}
		} catch (Exception e) {
//			e.printStackTrace();
			log.error(e.toString()+" "+e.getMessage(),e);
		}
		return result;
	}
	/**
	 * 修改配置的属性值
	 * @param conFileName 属性文件名，必须是类路径下的。
	 * @param section 所属模块
	 * @param propName 属性名
	 * @param newValue 要修改为的新值，newValue要不同与原有值
	 * @return true,找到这个propName节点，并且成功修改节点值，
	 */
	@SuppressWarnings("unchecked")
	public static boolean setConfValue(String conFileName,String section,String propName,String newValue){
		if(logDebugFlag){
			log.debug("read config property from file:classpath://"+conFileName);
			log.debug("section:"+section+" \t propertyName:"+propName+" : toValue;"+newValue);
		}
		
		SAXReader sreader= new SAXReader();
		Document document;
		boolean flag=false;
		try {
			File f = getAbsoluteFile(conFileName);
			if(!f.exists()){
				log.warn("配置文件不存在！"+f.getAbsolutePath());
				return false;
			}
			if(logDebugFlag){
				log.debug("文件路径："+f.getAbsolutePath());
			}
			document = sreader.read(f);
			document = sreader.read(f);
			Element root = document.getRootElement();
			Element sec;
			for(Iterator<Element> sects=root.elementIterator();sects.hasNext();){
				sec=sects.next();
				if(sec.attributeValue("name").equals(section)){
					Element prop ;
					for(Iterator<Element> props=sec.elementIterator();props.hasNext();){
						prop = props.next();
						if(prop.attributeValue("name").equalsIgnoreCase(propName)){
							String oldText = prop.getTextTrim();
							if(!oldText.equalsIgnoreCase(newValue)){ //新值和旧值不相等时才更改
								prop.setText(newValue);
								flag=true;
							}
						}
					}
				}
			}
			if(flag){
				if(logDebugFlag){
					log.debug("value changed");
				}
				OutputFormat format = OutputFormat.createPrettyPrint();
				format.setEncoding("utf-8");
				XMLWriter writer = new XMLWriter(new FileOutputStream(f),format);
//				document.addProcessingInstruction("target", "text");
				writer.write(document);
				writer.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.toString()+" "+e.getMessage(),e);
		}
		return flag;
	}
	/**
	 * 向配置文件中添加一个属性
	 * @param conFileName 配置文件名称 
	 * @param section 模块名
	 * @param propName 属性名
	 * @param value 属性值
	 * @return 添加结果标志
	 */
	@SuppressWarnings("unchecked")
	public static boolean addConfNode(String conFileName,String section,String propName,String value){
		if(logDebugFlag){
			log.debug("read config property from file:classpath://"+conFileName);
			log.debug("new value add to section:"+section+" \t propertyName:"+propName+" : value;"+value);
		}
//		
		SAXReader sreader= new SAXReader();
		Document document;
		boolean flag=false;
		boolean addFlag=true;
		try {
			File f = getAbsoluteFile(conFileName);
			if(!f.exists()){
				log.warn("配置文件不存在！"+f.getAbsolutePath());
				return false;
			}
			if(logDebugFlag){
				log.debug("文件路径："+f.getAbsolutePath());
			}
			document = sreader.read(f);
//			document.setXMLEncoding("utf-8");
			Element root = document.getRootElement();
			Element sec;
			Element opSection=null;
			for(Iterator<Element> sects=root.elementIterator();sects.hasNext();){
				sec=sects.next();
				if(sec.attributeValue("name").equals(section)){
					opSection=sec;
				}
			}
			sec=null;
			if(null==opSection){
				opSection=root.addElement("section").addAttribute("name", section);
				if(logDebugFlag){
					log.debug("new section ["+section+"] added!");
				}
			}
			Element prop;
			for(Iterator<Element> props = opSection.elementIterator();props.hasNext()&&addFlag;){
				prop = props.next();
				if(prop.attributeValue("name").equalsIgnoreCase(propName)){
					addFlag=false;//已经存在的要修改
				}
			}
			if(addFlag){//添加
				opSection.addElement("property").addAttribute("name", propName).setText(value);
				flag=true;
			}else{//如果已经有这个节点了，就修改节点值
				flag = setConfValue(conFileName, section, propName, value);
			}
		
			if(addFlag){ //添加
				if(logDebugFlag){
					log.debug("新的值添加到文件中了吗？"+flag);
				}
				OutputFormat format = OutputFormat.createPrettyPrint();
				format.setEncoding("utf-8");
				XMLWriter writer = new XMLWriter(new FileOutputStream(f),format);
//				document.addProcessingInstruction("target", "text");
				writer.write(document);
				writer.close();
			}else{
				if(logDebugFlag){
					log.debug("属性已经存在，修改 ");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.toString()+" "+e.getMessage(),e);
		}
		return flag;
	}
}
